/****************************************************************************
 *
 *  ALi (Shanghai) Corporation, All Rights Reserved. 2002 Copyright (C)
 *
 *  File: UpgradeInterface.cpp
 *
 *  Description: implement functions interface about upgrade module
 *		         
 *  History:
 *      Date		Author      Version		Comment
 *      ====        ======      =======		=======
 *  1   2007.5.23	Tony Wang	1.0			Create
 ****************************************************************************/

#include <types.h>
#include <sys_config.h>

#include <api/libc/printf.h>
#include <api/libc/string.h>
#include <api/libc/fastCRC.h>
#include <api/libchunk/chunk.h>
#include <bus/sci/sci.h>
#include <bus/flash/flash.h>
#include <hld/hld_dev.h>

#include "ErrorCode.h"
#include "Packet.h"
#include "UpgradeCommand_old.h"

#define BLOCK_HEADER_SIZE 128
#define MAX_BLOCK_NUMBER 16

extern UINT g_protocol_version;

/****************************************************************************
 *
 *  Name:		cmd_version
 *	Function:	command version return chunk info
 *	variable:	pVersion		-- protocol version (return value)
 *				chunk_info 		-- chunk info about command version (return value)
 *				
 *				
 *  
 ****************************************************************************/
extern GetChunk(BYTE *buffer, UINT32 nLen);

unsigned int cmd_version_old(UINT32 *pVersion)
{

	char szCommand[256] = "version -r\r";

	
	unsigned char szBuffer[BLOCK_HEADER_SIZE * MAX_BLOCK_NUMBER];
	unsigned char szCRC[4];
	int nBufLen = 0;

	//clean read buffer
	Sleep(50);
	Sleep(50);// 100 is to large parameter	
	com_clear_buffer();	

	int nLen = STRLEN(szCommand);
	if(com_send2back_tm((unsigned char *)szCommand, nLen, SENDCMDTIMEOUT) != SUCCESS)
	{
		return ERROR_SENDCOMMAND;
	}

	//read version info or chunck info buffer len 
	memset((void *)szBuffer, 0, BLOCK_HEADER_SIZE * MAX_BLOCK_NUMBER);
	if(com_read_tm(szBuffer, 2, 1000) != SUCCESS)
	{
		return ERROR_READDATA_TIMEOUT;
	}
	
	nBufLen = (szBuffer[0] << 8) + szBuffer[1];
	
	*pVersion = 0;
	if( nBufLen >= 0xb721) // transfer protocol version
	{
		
		*pVersion = nBufLen - 0xb700;

		if(com_read_tm(szBuffer, 2, 100) != SUCCESS)
		{
			return ERROR_READDATA_TIMEOUT;
		}
		nBufLen = (szBuffer[0] << 8) + szBuffer[1];
		
	}
	
	//read chunk info 
	if(com_read_tm(szBuffer, nBufLen, 5 * 1000) != SUCCESS)
	{
		return ERROR_READDATA_TIMEOUT;
	}
	//read 4B crc 
	if(com_read_tm(szCRC, 4, 100) != SUCCESS)
	{
		return ERROR_READDATA_TIMEOUT;
	}
	
	//check data crc
	int nCRC = (szCRC[0]<<24)+(szCRC[1]<<16)+(szCRC[2]<<8)+(szCRC[3]<<0);
	int nCRCVerify = MG_Table_Driven_CRC(0xFFFFFFFF, szBuffer, nBufLen);
	if(nCRCVerify != nCRC)
	{
		return ERROR_DATACRC;
		
	}
	
	GetChunk(szBuffer, nBufLen);
	
	return SUCCESS;
}

	
/****************************************************************************
 *
 *  Name:		cmd_address
 *	Function:	set start address
 *	variable:	addr -- start address
 *				
 *				
 *  
 ****************************************************************************/
unsigned int cmd_address_old(unsigned int addr)
{
	char szCommand[256];

	sprintf(szCommand, "address %u\r", addr);


	//clean read buffer
	Sleep(50);
	Sleep(50);// 100 is to large parameter	
	com_clear_buffer();	

	int nLen = STRLEN(szCommand);
	if(com_send2back_tm((unsigned char *)szCommand, nLen, SENDCMDTIMEOUT) != SUCCESS)
	{
		return ERROR_SENDCOMMAND;
	}

	//read answer
	unsigned char cAnswer = 0;
	if(com_read_tm(&cAnswer, 1, 1000) != SUCCESS)
	{
		return ERROR_READDATA_TIMEOUT;
	}

	if(cAnswer != 'O')
	{
		return ERROR_FUNCTION;
	}
	
	return SUCCESS;
}

/****************************************************************************
 *
 *  Name:		cmd_move
 *	Function:	move chunk
 *	variable:	index -- chunk index
 *				offset - chunk offset
 *				
 *  
 ****************************************************************************/
unsigned int cmd_move_old(unsigned int index,unsigned int offset)
{
	char szCommand[256];

	sprintf(szCommand, "move %u %u\r", index, offset);


	//clean read buffer
	Sleep(50);
	Sleep(50);// 100 is to large parameter	
	com_clear_buffer();	

	int nLen = STRLEN(szCommand);
	if(com_send2back_tm((unsigned char *)szCommand, nLen, SENDCMDTIMEOUT) != SUCCESS)
	{
		return ERROR_SENDCOMMAND;
	}



	//read answer
	unsigned char cAnswer = 0;
	if(com_read_tm(&cAnswer, 1, 10 * 1000) != SUCCESS)
	{
		return ERROR_READDATA_TIMEOUT;
	}

	if(cAnswer != 'O')
	{
		return ERROR_FUNCTION;
	}
	
	
	return SUCCESS;
}


/****************************************************************************
 *
 *  Name:		cmd_transferraw
 *	Function:	move chunk
 *	variable:	buffer - data buffer for transfer
 *				nBufLen	-- buffer len
 *				pfProgress 		-- callback function about progress
 *				pfUserAbort 	-- callback function about if user abort thread
 *  
 ****************************************************************************/
unsigned int cmd_transferraw_old(unsigned char *buffer, int nBufLen, 
		CALLBACK_PROGRESS pfProgress,  CALLBACK_USERABORT pfUserAbort)
{
	int i = 0;
	char szCommand[256];
    unsigned char data_buffer[PACKAGESIZE];

	sprintf(szCommand, "transferraw %d\r", nBufLen);


	//clean read buffer
	Sleep(50);
	Sleep(50);// 100 is to large parameter	
	com_clear_buffer();	

	int nLen = STRLEN(szCommand);
	if(com_send2back_tm((unsigned char *)szCommand, nLen, SENDCMDTIMEOUT) != SUCCESS)
	{
		return ERROR_SENDCOMMAND;
	}

	//read answer
	unsigned char cAnswer = 0;
	if(com_read_tm(&cAnswer, 1, 1000) != SUCCESS)
	{
		return ERROR_READDATA_TIMEOUT;
	}

	if(cAnswer != 'O')
	{
		return ERROR_FUNCTION;
	}

	int nErrCount = 0;
	unsigned char *pos = (unsigned char *)(buffer-((unsigned char *)FLASH_BASE));;
	unsigned int nTransLen = PACKAGESIZE;
	unsigned char szCRCBuff[4];

	nLen = 0;
	while(nLen < nBufLen && nErrCount < TRANSFER_RETRY_TIMES)
	{
		//check if user cancel data transfer
		if(pfUserAbort != NULL && (*pfUserAbort)() == TRUE)
		{
			return ERROR_USERABORT;
		}

		if((nLen + PACKAGESIZE) > nBufLen)
			nTransLen = nBufLen - nLen;
        MEMSET(data_buffer,0xFF,PACKAGESIZE);
		sto_get_data((struct sto_device*)dev_get_by_id(HLD_DEV_TYPE_STO, 0),data_buffer,(UINT32)pos,(INT32)nTransLen);
		int nCRC = MG_Table_Driven_CRC(0xFFFFFFFF, (unsigned char *)data_buffer, nTransLen);
		
		for(i = 0; i < 4; i++)
		{
			szCRCBuff[i] = (nCRC>>((3-i)*8))&0xFF;
		}

		/* send one package*/
		if(nTransLen != com_send(data_buffer, nTransLen))
		{
			return ERROR_SENDDATA;
		}
			
		
		/* send 4 byte CRC*/
		if(4 != com_send(szCRCBuff, 4))
		{
			return ERROR_SENDDATA;
		}

		cAnswer = 0;
		if(com_read_tm(&cAnswer, 1, 10 * 1000) != SUCCESS)
		{
			return ERROR_READDATA_TIMEOUT;
		}


		if(cAnswer == 'O')
		{
			nLen += nTransLen;
			pos += nTransLen;
			nErrCount = 0;

			int nPercent = nLen * 100 / nBufLen;
			(*pfProgress)(nTransLen);
						
		}
		else if(cAnswer == 'E')
			nErrCount++;
		else
		{
			return ERROR_NORECOGNIZEANSOW;
		}
			
	}

	if(nErrCount >= TRANSFER_RETRY_TIMES)
	{
		return ERROR_OVERLOADRETRYTIME;
	}
	
	return SUCCESS;
}

/****************************************************************************
 *
 *  Name:		cmd_burn
 *	Function:	burn flash
 *	variable:	pfProgress 		-- callback function about progress
 *				
 *								
 *  
 ****************************************************************************/
unsigned int cmd_burn_old(int nBurnSize, CALLBACK_PROGRESS pfProgress, BOOL bCareReturn)
{

	char szCommand[256] = "burn\r";


	//clean read buffer
	Sleep(50);//
	Sleep(50);// 100 is to large parameter	
	com_clear_buffer();	

	int nLen = STRLEN(szCommand);
	if(com_send2back_tm((unsigned char *)szCommand, nLen, SENDCMDTIMEOUT) != SUCCESS)
	{
		return ERROR_SENDCOMMAND;
	}

	unsigned char szBuffer[32];
	//read answer
	unsigned char cAnswer = 0;
	if(com_read_tm(&cAnswer, 1, 1000) != SUCCESS)
	{
		return ERROR_READDATA_TIMEOUT;
	}

	if(cAnswer != 'O')
	{
		return ERROR_FUNCTION;
	}
	
	if(!bCareReturn)
		return SUCCESS;
	
	int nReturn = GENERIC_ERROR;
	while(1)
	{
		memset(szBuffer, 0, 32);
		if(com_read_tm(szBuffer, 1, 1000 * 30) != SUCCESS)
		{
			return ERROR_READDATA_TIMEOUT;
		}
		
		if(szBuffer[0] == 'B')//Burning
		{
			if(com_read_tm(szBuffer, 6, 1000) != SUCCESS)
			{
				return ERROR_READDATA_TIMEOUT;
			}
			szBuffer[4]='\0';
			int nCmdLen = atoi((char *)szBuffer) * 1024;
			int nProcess = nCmdLen * 100 / nBurnSize;
			if(nProcess < 0 )
				nProcess = 0;
			else if (nProcess > 100)
				nProcess = 100;
			(*pfProgress)(nProcess);
		}
		else if(szBuffer[0] == 'F')
		{
			(*pfProgress)(100);
			nReturn = SUCCESS;
			break;
		}
		else if(szBuffer[0] == 'E')
		{
			if(com_read_tm(szBuffer, 8, 1000) != SUCCESS)
			{
				return ERROR_READDATA_TIMEOUT;
			}
			szBuffer[7]='\0';
			return ERROR_BURN;
		}
	}
	
	return nReturn;
}


/****************************************************************************
 *
 *  Name:		cmd_reboot
 *	Function:	reboot target
 *	variable:	
 *				
 *				
 *  
 ****************************************************************************/
unsigned int cmd_reboot_old()
{

	char szCommand[256] = "reboot\r";


	//clean read buffer
	com_clear_buffer();	
	
	int nLen = STRLEN(szCommand);
	if(com_send2back_tm((unsigned char *)szCommand, nLen, SENDCMDTIMEOUT) != SUCCESS)
	{
//		SetLastError(CMD_REBOOT, SEND_CMD, ERROR_SENDCOMMAND,
//			"", "", "");
		return ERROR_SENDCOMMAND;
	}

	return SUCCESS;
}
